package org.internna.expensetracker.model.support;

import java.util.TreeSet;
import java.util.Collection;
import java.text.NumberFormat;
import org.springframework.util.CollectionUtils;
import org.internna.expensetracker.model.Account;
import org.internna.expensetracker.model.AccountTransaction;
import org.internna.expensetracker.model.Investment;
import org.internna.expensetracker.model.InvestmentTransaction;

public final class InvestmentStatus {

	private final Account account;
	private final Investment investment;
	private boolean preferAmount = false;
	private Collection<InvestmentTransaction> operations;
	private Double buy = 0D, sell = 0D, interest = 0D, gainLoss = 0D, percentage = 0D, quantity = 0D;

	public InvestmentStatus(Account account, Investment investment) {
		this.account = account;
		this.investment = investment;
	}

	public void add(AccountTransaction transaction) {
		Double total = transaction.getInvestment().getQuantity();
		preferAmount |= total <= 0D;
		String subcat = transaction.getSubcategory().getCategory();
		Double amount = transaction.getAmount().abs().doubleValue();
		if ("category.investment.buy".equals(subcat)) {
			buy += amount;
			quantity += total;
		} else if ("category.investment.sell".equals(subcat)) {
			sell += amount;
			quantity -= total;
		} else {
			interest += amount;
		}
		calculateGainLoss();
		add(transaction.getInvestment());
	}

	private void add(InvestmentTransaction investmentTransaction) {
		if (operations == null) {
			operations = new TreeSet<InvestmentTransaction>();
		}
		operations.add(investmentTransaction);
	}

	public String getAsJSONString() {
		NumberFormat nFormatter = NumberFormat.getNumberInstance(account.getLocale());
		NumberFormat cFormatter = NumberFormat.getCurrencyInstance(account.getLocale());
		StringBuilder builder = new StringBuilder("{operationDate:'', id: ")
			.append(investment.getId()).append(", label: '")
			.append(investment.getName()).append("', buy: '")
			.append(formatAmount(cFormatter, buy)).append("', sell: '")
			.append(formatAmount(cFormatter, sell)).append("', interest: '")
			.append(formatAmount(cFormatter, interest)).append("', gainLoss: '")
			.append(formatAmount(cFormatter, gainLoss)).append("', pctg: '")
			.append(nFormatter.format(percentage)).append("%', quantity: '")
			.append(quantity > 0 ? nFormatter.format(quantity) : "").append("', price: '")
			.append(formatAmount(cFormatter, investment.getCurrentPrice())).append("', operations: [");
		if (!CollectionUtils.isEmpty(operations)) {
			for (InvestmentTransaction transaction : operations) {
				builder.append(transaction.getAsJSONString()).append(",");
			}
			builder.deleteCharAt(builder.length() - 1);
		}
		return builder.append("], quant: ").append(quantity).append("}").toString();
	}

	protected String formatAmount(final NumberFormat formatter, final Double amount) {
		return amount == null || amount == 0D ? "" : formatter.format(amount.doubleValue());
	}

	protected void calculateGainLoss() {
		gainLoss = preferAmount ? interest : interest + sell  + (quantity * investment.getCurrentPrice()) - buy;
		percentage = 100 * gainLoss / buy;
	}

}
